#include "../../logging/Logging.h"
#include "../../net/EventLoop.h"
#include "../../net/InetAddress.h"
#include "../../net/TcpClient.h"
#include "../../net/TcpServer.h"

#include <queue>
#include <utility>

#include <stdio.h>
#include <unistd.h>

#include <string>

using namespace yhaida;
using std::string;

/*
 * 1 : N
 */
class DemuxServer : Utils::nocapyable
{
public:
    DemuxServer(EventLoop *loop,
                const InetAddress &listenAddr,
                const InetAddress &socksAddress);
    ~DemuxServer() = default;

    void start();

    void onServerConnection(const TcpConnectionPtr &conn);
    void onServerMessage(const TcpConnectionPtr &conn, Buffer *buffer, Timestamp);
    void doCommand(const string &cmd);

    void onSocksConnection(int connId,
                           const TcpConnectionPtr &conn);
    void onSocksMessage(int connId,
                        const TcpConnectionPtr &conn,
                        Buffer *buffer, Timestamp);

    void sendServerPacket(int connId, Buffer *buffer);

public:
    typedef std::shared_ptr<TcpClient> TcpClientPtr;
    struct client_conn
    {
        int connID;
        TcpClientPtr client;
        TcpConnectionPtr clientConn;
        Buffer pending;
    };

private:
    // const int kMaxConns = 1;
    const size_t kMaxPacketLen = 255;
    const size_t kHeaderLen = 3;

private:
    EventLoop *_loop;
    TcpServer _server;
    TcpConnectionPtr _serverConn;
    const InetAddress _sockAddress;
    std::map<int, client_conn> _sockConnections;
};